package main

import (
	"context"
	"encoding/json"
	"fmt"
	"hxzkx/global/model"
	"hxzkx/global/pkg"
	payment "hxzkx/kitex_gen/hertz/payment"
	"math/rand"
	"strconv"
	"time"

	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
)

// PaymentServiceImpl implements the last service interface defined in the IDL.
type PaymentServiceImpl struct{}

// CreatePaymentOrder implements the PaymentServiceImpl interface.
func (s *PaymentServiceImpl) CreatePaymentOrder(ctx context.Context, req *payment.CreatePaymentOrderReq) (resp *payment.CreatePaymentOrderResp, err error) {
	// TODO: Your code here...
	count_key := fmt.Sprintf("%s:req_pay_create:count", req.PassengerId)
	count, _ := model.RDB.Get(model.Ctx, count_key).Int()
	if count >= 10 {
		return nil, fmt.Errorf("请求过于频繁，请稍后再试")
	}
	if count == 9 {
		model.RDB.Expire(model.Ctx, count_key, 600)
	}
	model.RDB.Incr(model.Ctx, count_key)
	key := fmt.Sprintf("%s:req_pay_create", req.PassengerId)
	url := model.RDB.Get(model.Ctx, key).Val()
	if url == "" {
		id, _ := strconv.Atoi(req.OrderId)
		var PayOrder = model.PaymentOrder{
			OrderId:        id,
			PaymentOrderId: rand.Intn(90000+10000) + int(time.Now().UnixMilli()),
			Amount:         float64(req.Amount),
			PaymentMethod:  req.PaymentMethod,
		}
		err, s2 := pkg.CreatePayLink(PayOrder)
		if err != nil {
			return nil, err
		}
		model.DB.Create(&PayOrder)
		resp = &payment.CreatePaymentOrderResp{
			PaymentOrderId: fmt.Sprintf("%d", PayOrder.PaymentOrderId),
			PayUrl:         s2,
			Timeout:        600,
			Status:         1,
		}
		data, _ := json.Marshal(resp)
		model.RDB.Set(model.Ctx, key, data, 600)
	} else {
		json.Unmarshal([]byte(url), resp)
	}
	ExipreOrderKey := fmt.Sprintf("order_notpay")
	model.RDB.ZAdd(model.Ctx, ExipreOrderKey, redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: resp.PaymentOrderId,
	})
	return resp, nil
}

// SyncPaymentStatus implements the PaymentServiceImpl interface.
func (s *PaymentServiceImpl) SyncPaymentStatus(ctx context.Context, req *payment.SyncPaymentStatusReq) (resp *payment.SyncPaymentStatusResp, err error) {
	// TODO: Your code here...
	var po model.PaymentOrder
	model.DB.Where("id = ?", req.PaymentOrderId).Find(&po)
	var pr = model.PaymentRecord{
		SyncId:         fmt.Sprintf("%d", time.Now().UnixMilli()+int64(rand.Intn(10000))),
		PaymentOrderId: int(po.ID),
		ChannelName:    po.PaymentMethod,
		SyncTime:       time.Now(),
		Status:         fmt.Sprintf("%d", req.Status),
	}
	model.DB.Model(&po).Create(&pr)
	resp = &payment.SyncPaymentStatusResp{
		Success: true,
		Msg:     "ok",
	}
	return resp, nil
}

// PaymentLog implements the PaymentServiceImpl interface.
func (s *PaymentServiceImpl) PaymentLog(ctx context.Context, req *payment.PaymentLogReq) (resp *payment.PaymentLogResp, err error) {
	// TODO: Your code here...
	var DB = model.DB.Model(&model.PaymentRecord{})
	DB = DB.Joins("join payment_orders on payment_records.payment_order_id = payment_orders.id")
	DB = DB.Joins("join orders on orders.id = payment_orders.order_id")
	DB = DB.Joins("join passengers on orders.passenger_id = passengers.id")
	if req.Status != 0 {
		DB = DB.Where("orders.status = ?", req.Status)
	}
	if req.PaymentMethod != "" {
		DB = DB.Where("payment_orders.payment_method = ?", req.PaymentMethod)
	}
	if req.OrderCode != "" {
		DB = DB.Where("orders.order_code = ?", req.OrderCode)
	}
	if req.PassengerPhone != "" {
		DB = DB.Where("passengers.phone like ?", "%"+req.PassengerPhone+"%")
	}
	//if req.PayStater != "" {
	//	strate_time, _ := time.Parse(req.PayStater, time.DateTime)
	//	DB = DB.Where("payment_orders.created_at > ?", strate_time)
	//}
	//if req.PayEnd != "" {
	//	end_time, _ := time.Parse(req.PayEnd, time.DateTime)
	//	DB = DB.Where("payment_orders.created_at < ?", end_time)
	//}
	var Data []struct {
		PassengerId int       `json:"passenger_id"`
		Phone       string    `json:"phone"`
		PayOrderId  int       `json:"pay_order_id"`
		OrderId     string    `json:"order_id"`
		Total       float64   `json:"total"`
		Method      string    `json:"method"`
		Status      int       `json:"status"`
		PatAt       time.Time `json:"pat_at"`
	}
	DB.Limit(25).Select("passengers.id as passenger_id,passengers.phone as phone,payment_orders.id as pay_order_id,orders.order_code as order_id,orders.total as total,payment_orders.payment_method as method,orders.status as status").Find(&Data)
	var ResData []*payment.FormPaymentLog
	for _, datum := range Data {
		var res = payment.FormPaymentLog{
			PassengerId:    fmt.Sprintf("%d", datum.PassengerId),
			PassengerPhone: datum.Phone,
			PaymentId:      fmt.Sprintf("%d", datum.PayOrderId),
			OrderCode:      datum.OrderId,
			Total:          float32(datum.Total),
			PaymentMethod:  datum.Method,
			Status:         int32(datum.Status),
			PayAt:          datum.PatAt.String(),
		}
		ResData = append(ResData, &res)
	}
	resp = &payment.PaymentLogResp{
		PaymentLogs: ResData,
	}
	return resp, nil
}

// PaymentMethodGet implements the PaymentServiceImpl interface.
func (s *PaymentServiceImpl) PaymentMethodGet(ctx context.Context, req *payment.PaymentMethodGetReq) (resp *payment.PaymentMethodGetResp, err error) {
	// TODO: Your code here...
	var pm []model.PaymentMethod
	model.DB.Model(&model.PaymentMethod{}).Where("passenger_id = ?", req.PassengerId).Find(&pm)
	methods := []string{}
	def := ""
	for _, method := range pm {
		methods = append(methods, method.PaymentMethodType)
		if method.IsDefault == 1 {
			def = method.PaymentMethodType
		}
	}
	resp = &payment.PaymentMethodGetResp{
		PaymentMethod: methods,
		Def:           def,
	}
	return resp, nil
}

// PaymentMethodBind implements the PaymentServiceImpl interface.
func (s *PaymentServiceImpl) PaymentMethodBind(ctx context.Context, req *payment.PaymentMethodBindReq) (resp *payment.PaymentMethodBindResp, err error) {
	// TODO: Your code here...
	id, _ := strconv.Atoi(req.PassengerId)
	var pay_method = model.PaymentMethod{
		Model:             gorm.Model{},
		PassengerId:       id,
		PaymentMethodType: req.PaymentMethod,
		PaymentAccount:    req.AccountData,
		IsDefault:         int(req.IsDef),
	}
	if err := pkg.PayMethodAccountIsOk(pay_method); err != nil {
		return nil, err
	}
	var pay model.PaymentMethod
	model.DB.Model(&model.PaymentMethod{}).Where("passenger_id = ? and payment_method_type = ?", req.PassengerId, req.PaymentMethod).Find(&pay)
	if pay.ID != 0 {
		return nil, fmt.Errorf("该方式已绑定")
	}
	var Count int64
	if err := model.DB.Model(&model.PaymentMethod{}).Where("passenger_id=?", req.PassengerId).Count(&Count).Error; err != nil {
		return nil, err
	}
	if Count >= 5 {
		return nil, fmt.Errorf("已经达到绑定上限")
	}
	resp = &payment.PaymentMethodBindResp{
		PassengerId:       fmt.Sprintf("%d", pay_method.PassengerId),
		PaymentMethodType: pay_method.PaymentMethodType,
		PaymentAccount:    pay_method.PaymentAccount,
		IsDefault:         int32(pay_method.IsDefault),
		BindTime:          pay_method.CreatedAt.String(),
	}
	return
}
